<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>让整个网页盯着你 眼球跟踪教学</title>
  <style>
    html,
    body {
      width: 100%;
      height: 100%;
      margin: 0;
      padding: 0;
      overflow: hidden;
      background: #4154ff;
      display: flex;
      justify-content: center;
      align-items: center;
    }

    /* 2.1 配置 主容器 相关样式 */
    .eye-container {
      width: 600px;
      height: 600px;
      position: relative;
      /* 创建9行9列的网格 */
      display: grid;
      grid-template: repeat(9, 1fr) / repeat(9, 1fr);
    }

    .eye {
      width: 60px;
      height: 60px;
      background-color: #fff;
      border-radius: 50%;
      display: flex;
      justify-content: center;
      align-items: center;
      overflow: hidden;
      /* 初始内阴影样式，添加模糊效果 */
      box-shadow: 0 0 10px #000 inset 0px 0px 10px rgba(0, 0, 0, 0.3);
      transition: box-shadow 0.2s ease-out;
    }

    .pupil {
            width: 25px;
            height: 25px;
            background-color: #000000;
            border-radius: 50%;
            position: relative;
            transition: transform 0.2s ease-out;
    }
  </style>
</head>

<body>
  <!-- 1. 主容器 -->
  <div class="eye-container"></div>
</body>

<script>
  // 3.1 清除控制台
  console.clear() // ✨✨写上该语句, 打开网页会自动在控制台输出: 已清除控制台

  const eyeContainer = document.querySelector('.eye-container')
  // 3.2 创建眼睛
  for (let i = 0; i < 81; i++) {
    createEye()
  }
  // 3.4同步 ->获取所有眼睛
  const eyes = document.querySelectorAll('.eye')

  // 3.3 函数：创建眼睛
  // 🔥🔥本质1: 通过创建新节点的方式, 往[主容器]内添加对应子节点...
  function createEye() {
    // 3.3.1 创建节点
    const eye = document.createElement('div')
    const pupil = document.createElement('div')

    // 3.3.2 给节点添加 ->样式名称
    // 💥(回顾1)className: 如果已经确定元素为某个样式名称了, 就可以使用className.
    eye.className = 'eye'
    pupil.className = 'pupil'

    // 3.3.end 添加子节点到不同容器上
    eye.appendChild(pupil)
    eyeContainer.appendChild(eye)
  }

  // 3.4 (on注册)鼠标移动事件: 更新瞳孔位置
  document.body.onpointermove = (e) => {
    // 🔥🔥本质2: 给所有【眼睛】子节点、遍历注册上、鼠标移动事件
    eyes.forEach((eye) => {
      const pupil = eye.querySelector('.pupil')

      // 3.4.1 获取眼睛的中心点
      // 🔥🔥本质3: 眼睛距离父容器左边距离 + 眼睛一半宽度 = 当前眼睛相对于其父容器的中心点位置(可自行测试查看滴)
      const eyeRect = eye.getBoundingClientRect()
      const eyeCenterX = eyeRect.left + eyeRect.width / 2
      const eyeCenterY = eyeRect.top + eyeRect.height / 2

      // 计算距离比例
      const dx = (e.clientX - eyeCenterX) / eyeRect.width
      const dy = (e.clientY - eyeCenterY) / eyeRect.height
      // 计算瞳孔新的x, y位置，限制其不能超出眼睛的范围
      const distance = Math.sqrt(dx * dx + dy * dy)
      const maxDistance = 0.9// 允许的最大偏移量比例
      const clampedDistance = Math.min(distance, maxDistance)

      // 计算吸附效果
      const angle = Math.atan2(dy, dx)
      const pupilX = Math.cos(angle) * clampedDistance * (eyeRect.width / 2 - pupil.offsetWidth / 2)
      const pupilY = Math.sin(angle) * clampedDistance * (eyeRect.height / 2 - pupil.offsetHeight / 2)

      // 更新瞳孔位置
      pupil.style.transform = `translate(${pupilX}px, ${pupilY}px)`

      // 动态更新内阴影效果，阴影在瞳孔的对立面
      const shadowOffsetX = pupilX / 4;
      const shadowOffsetY = pupilY / 2;
      const shadowBlur = 10; // 模糊半径
      eye.style.boxShadow =
        `inset ${shadowOffsetX}px ${shadowOffsetY}px ${shadowBlur}px rgba(0, 0, 0, 0.4)`;
    })
  }

  // 3.end 鼠标离开事件：重置瞳孔位置和内阴影
  document.body.onpointerleave = () => {
    eyes.forEach((eye) => {
      const pupil = eye.querySelector('.pupil')
      pupil.style.transform = 'translate(0, 0)'

      // 重置内阴影，保留模糊效果
      eye.style.boxShadow = 'inset 0px 0px 10px rgba(0, 0, 0, 0.4)';
    })
  }
</script>

</html>